package com.xing.game.server;

import com.xing.game.bean.api.Bean;
import com.xing.game.util.DisruptorExecutor;
import java.util.concurrent.*;

@Bean(type = ExcutorWorkers.class)
public class ExcutorWorkers {

	public static final int GAME_WORKER_COUNT = 64;
	public static final int GAME_WORKER_MOD_VALUE = GAME_WORKER_COUNT - 1;
	private DisruptorExecutor dbWorkers;
	private DisruptorExecutor[] gameWorkers;
	private ScheduledExecutorService refresherWorker;
	public static final int CPU_NUMBERS = Runtime.getRuntime().availableProcessors();

	private void initWorkers(){
		dbWorkers = new DisruptorExecutor("DB_WORKER", CPU_NUMBERS * 2, 65536 << 1);
		gameWorkers = new DisruptorExecutor[GAME_WORKER_COUNT];
		for(int idx = 0; idx < GAME_WORKER_COUNT; idx ++) {
			gameWorkers[idx] = new DisruptorExecutor("GAME_WORKER#" + idx, 4096 << 2);
		}
		refresherWorker = Executors.newScheduledThreadPool(CPU_NUMBERS * 2, new ThreadFactory() {
			@Override
			public Thread newThread(Runnable r) {
				Thread t = new Thread(r, "REFRESHER_WORKER");
				t.setPriority(Thread.MAX_PRIORITY);
				return t;
			}
		});
	}
	
	private void initGameTime(){
//		GameInfo.currentMilliSecond = System.currentTimeMillis();
//		refresherWorker.scheduleAtFixedRate(new Runnable() {
//			@Override
//			public void run() {
//				GameInfo.currentMilliSecond = System.currentTimeMillis();
//			}
//		}, 1, 1, TimeUnit.MILLISECONDS);
	}
	
	private void schedulerUpdate(){
		
	}

	public void init(){
		initWorkers();
		initGameTime();
		schedulerUpdate();
	}
	
	public void schedulerTask(Runnable command, long initialDelay, long period, TimeUnit unit) {
		refresherWorker.scheduleAtFixedRate(command, initialDelay, period, unit);
	}
	
	public void schedulerTask(Runnable command,long initialDelay,TimeUnit unit){
		refresherWorker.schedule(command, initialDelay, unit);
	}
	
	public void executeTask(Runnable task) {
		dbWorkers.execute(task);
	}
	
	public int getModValue(int value) {
		return value & GAME_WORKER_MOD_VALUE;
	}
	
	public int getModValue(long value) {
		return (int) (value & GAME_WORKER_MOD_VALUE);
	}
	
	public DisruptorExecutor getGameExecutor(int value) {
		return gameWorkers[getModValue(value)];
	}
	
	public DisruptorExecutor getGameExecutor(long value) {
		return gameWorkers[getModValue(value)];
	}
	
	public Executor getDbWorkers() {
		return dbWorkers;
	}
	
	public void stop(){
		try {
			refresherWorker.shutdown();
			try {
				refresherWorker.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
			} catch (Throwable e) {
				e.printStackTrace();
			}
			for (DisruptorExecutor executor : gameWorkers) {
				executor.shutdown();
			}
		} catch (Throwable e) {
			e.printStackTrace();
		}finally{
			try {
				
			} finally {
				dbWorkers.shutdown();
			}
		}
	}
	
}
